package com.greateamd.timetableasy.client.widgets.planning;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.CalendarUtil;
import com.greateamd.timetableasy.client.mvc.view.TimeTableasyPage;
import com.greateamd.timetableasy.client.widgets.ClassicLabel;
import com.greateamd.timetableasy.client.widgets.ClassicLargeLabel;
import com.greateamd.timetableasy.domain.Event;
import com.greateamd.timetableasy.domain.User;

public class PlanningWidget extends Composite {
	
	public enum PlanningType {DAY(1),WEEK(7),MONTH(31);
		int days;
		private PlanningType(int days) {
			this.days = days;
		}};
	
	@UiTemplate("PlanningWidget.ui.xml")
	interface PlanningWidgetUIBinder extends UiBinder<Widget, PlanningWidget> {}
	private static PlanningWidgetUIBinder uiBinder = GWT.create(PlanningWidgetUIBinder.class);

	@UiField Button exportAsICal;
	@UiField Button planningAsList;
	@UiField Button planningAsListByLabel;
	@UiField Button planningAsListByDate;
	@UiField(provided=true) Grid gridVisual = new Grid(16,7);
	@UiField(provided=true) Grid gridList = new Grid(2,7);

	private DateTimeFormat dateFormater = DateTimeFormat.getFormat("dd MMM");
	private PlanningType type;
	private Date startDate;
	private List<Event> displayEvents = new ArrayList<Event>();
	
	
	public PlanningWidget() {
		initWidget(uiBinder.createAndBindUi(this));
		initGridVisual();
	}
	

	@UiHandler("planningAsListByLabel")
	void onPlanningAsListByLabelBtClick(ClickEvent e){
		Collections.sort(displayEvents,new Comparator<Event>(){
			@Override
			public int compare(Event o1, Event o2) {
				return o1.getLabel().compareTo(o2.getLabel());
			}});
		refreshGridList();
	}
	
	@UiHandler("planningAsListByDate")
	void onPlanningAsListByDateBtClick(ClickEvent e){
		Collections.sort(displayEvents,new Comparator<Event>(){
			@Override
			public int compare(Event o1, Event o2) {
				return o1.getStartDate().compareTo(o2.getStartDate());
			}});
		refreshGridList();
	}
	
	
	@UiHandler("planningAsList")
	void onPlanningAsListBtClick(ClickEvent e){
		setGridListVisible(!gridList.isVisible());
	}
	
	@UiHandler("exportAsICal")
	void onExportAsICalBtClick(ClickEvent e){
		String icalValue = "<hr/>";
		if(!displayEvents.isEmpty()){
			for(Event event : displayEvents){
				icalValue += event.getICalAsHtml()+"<br/><br/>";
			}
			final HTML showIcalValue = new HTML();
			showIcalValue.setStyleName("ClassicLittleLabel");
			showIcalValue.setHTML(icalValue);
			final VerticalPanel vp = new VerticalPanel();
			vp.add(new ClassicLargeLabel("Copy/Paste this content into a empty .ics file"));
			vp.add(showIcalValue);
			
			final ScrollPanel scroll = new ScrollPanel(vp);
			scroll.setSize("600px", "400px");
			final PopupPanel popup = new PopupPanel(true, true);
			popup.setGlassEnabled(true);
			popup.setAnimationEnabled(true);
			popup.setWidget(scroll);
			popup.show();
			popup.center();
		} else {
			Window.alert("No events found");
		}
	}
	
	private void setGridListVisible(final boolean setListVisible){
		gridList.setVisible(setListVisible);
		planningAsListByLabel.setVisible(setListVisible);
		planningAsListByDate.setVisible(setListVisible);
		gridVisual.setVisible(!setListVisible);
		if(setListVisible){
			refreshGridList();
		}
	}
	
	/**
	 * Add a event to the planning if the event is viable.
	 * @param event
	 */
	public void addEvent(final Event event,final User userViewRequest,final TimeTableasyPage pageViewRequest){
		if(isAvailableEvent(event)){
			displayEvents.add(event);
			//Column to draw
			final int columnX = CalendarUtil.getDaysBetween(startDate,event.getStartDate())+1;
			//Row index where I begin to draw
			final int startDrawRowEvent = event.getStartDate().getHours()-6;
			
			//Calculation of the event duration that can be represent onto the planning panel
			int whileDuration = event.getDuration() - ((startDrawRowEvent > 0)? 0 : startDrawRowEvent);
			final int alpha = (whileDuration+startDrawRowEvent) - 16;
			whileDuration -= (alpha <= 0 )? 0 : alpha;
			
			for(int i = 0; i < whileDuration;i++){
				//Get widget (event) already present in the table case
				final Widget w = gridVisual.getWidget(startDrawRowEvent+i, columnX);
				//If one exist
				if(w != null){
					w.removeFromParent();
					final HorizontalPanel cumulPanel = new HorizontalPanel();
					cumulPanel.add(w);
					cumulPanel.add(event.getIconPanel(userViewRequest,pageViewRequest));
					gridVisual.setWidget(startDrawRowEvent+i,columnX, cumulPanel);
				} else {
				//else is the first event
					gridVisual.setWidget(startDrawRowEvent+i,columnX, event.getIconPanel(userViewRequest,pageViewRequest));
				}
			}
			if(gridList.isVisible()){
				refreshGridList();
			}
		}
		
	}
	
	/**
	 * Check if the Event arg is valid to show for the current planning state.
	 * @param event
	 * @return the event's viability
	 */
	private boolean isAvailableEvent(final Event event) {
		final int daysAlpha = CalendarUtil.getDaysBetween(startDate,event.getStartDate());
		if(daysAlpha >= 0 && daysAlpha < type.days){
			return true;
		}
		return false;
	}

	/**
	 * Draw the hours and resize the grid
	 */
	private void initGridVisual() {
		int y = 1;
		for(int i = 7; i <= 21 ; i ++){
			gridVisual.setWidget(y, 0, new ClassicLabel(i+"h"));
			if (y%2 == 0)
			   gridVisual.getRowFormatter().setStyleName(y++,"PlanningRowAlternate1");
			else
			   gridVisual.getRowFormatter().setStyleName(y++,"PlanningRowAlternate2");
		}
		gridVisual.getColumnFormatter().setWidth(0, "50px");
		for(int i = 1;gridVisual.getColumnCount() > i ; i++){
			gridVisual.getColumnFormatter().setWidth(i, "150px");
			gridVisual.getCellFormatter().setHorizontalAlignment(0, i, HasAlignment.ALIGN_CENTER);
		}
		gridVisual.setBorderWidth(1);
		gridVisual.getColumnFormatter().setStyleName(0, "PlanningCol");
		gridVisual.getRowFormatter().setStyleName(0, "PlanningRow");
	}

	private void initGridList() {
		gridList.setWidget(0, 0, new ClassicLabel("Label"));
		gridList.setWidget(0, 1, new ClassicLabel("Start date"));
		gridList.setWidget(0, 2, new ClassicLabel("Location"));
		gridList.setWidget(0, 3, new ClassicLabel("Type"));
		gridList.setWidget(0, 4, new ClassicLabel("Modality"));
		gridList.setWidget(0, 5, new ClassicLabel("Dispenser"));
		gridList.setWidget(0, 6, new ClassicLabel("Duration"));
		gridList.getRowFormatter().setStyleName(0, "PlanningRow");
		gridList.setBorderWidth(2);
	}
	
	private void refreshGridList() {
		gridList.resize(displayEvents.size()+1, 7);
		initGridList();
		int i = 1;
		DateTimeFormat dateFormater = DateTimeFormat.getFormat("dd MMM HH'h'");
		for(Event event : displayEvents){
			gridList.getRowFormatter().setStyleName(i, event.getEventType().getColorStyle(event.getEventModality()));
			gridList.setWidget(i,0, new ClassicLabel(event.getLabel()));
			gridList.setWidget(i,1, new ClassicLabel(dateFormater.format(event.getStartDate())));
			gridList.setWidget(i,2, new ClassicLabel(event.getLocation()));
			gridList.setWidget(i,3, new ClassicLabel(event.getEventType().getText()));
			gridList.setWidget(i,4, new ClassicLabel(event.getEventModality().getText()));
			gridList.setWidget(i,5, new ClassicLabel(event.getDispenser()));
			gridList.setWidget(i++,6, new ClassicLabel(Integer.toString(event.getDuration())));
		}
	}
	
	/**
	 * Clear planning's events widget.
	 * Re-draw the calendar, take care of args. 
	 * @param startDate the date of planning start to show event
	 * @param type type of Calendar (day, week, month, ...)
	 */
	public void setStartDate(Date startDate,PlanningType type){
		this.type = type;
		this.startDate = startDate;
		Date toPrintDayDate = CalendarUtil.copyDate(startDate);
		
		displayEvents.clear();
		gridVisual.clear(false);
		gridVisual.resize(16,type.days+1);
		for(int i = 1 ; i <= type.days;i++){
			gridVisual.setWidget(0, i, new ClassicLabel(dateFormater.format(toPrintDayDate)));
			CalendarUtil.addDaysToDate(toPrintDayDate, 1);
		}
		initGridVisual();
	}
}

